﻿using System;
using System.Collections;
using System.Text;
using System.Xml;
using InfoJetSoft.Service.Entity;
using InfoJetSoft.Service.Util;

namespace InfoJetSoft.Service.Worker
{
	//对使用style作为条件格式手段的控件添加JetConstant.HTML_CONDITION_FORMAT属性。
	class XSNViewFormatConditionFormatStyleWorker
	{
		
		//测试见D:\InfoPath\Forms2003\Condition Formatting目录。
		public static void  formatConditionFormatStyle(View view)
		{

			XmlElement root = view.Doc.DocumentElement;
			string xdBinding = NamespaceUtil.toFullName(view.XdPrefix, JetConstant.XD_binding);
			
			//这样的控件一般定义其定义类似于<span class="xdTextBox"> <xsl:attribute name="style"> WIDTH: 130px; </xsl:attribute> </span>。
			//见All Condition Format Controls.xsn中的view1.xsl。
			string xslAttributeName = NamespaceUtil.toFullName(view.XslPrefix, "attribute");
			string styleAttributeFilter = "//" + xslAttributeName + "[@name='style']";

            StringBuilder whenFilterBuffer = new StringBuilder();
            whenFilterBuffer.Append(NamespaceUtil.toFullName(view.XslPrefix, "choose"));
            whenFilterBuffer.Append("/");
            whenFilterBuffer.Append(NamespaceUtil.toFullName(view.XslPrefix, "when"));
            string whenFilter = whenFilterBuffer.ToString();
			
			XmlNodeList styleAttributeXmlNodeList = DOMUtil.selectNodes(root, styleAttributeFilter, 0, view.NsResolver);
			foreach (XmlElement styleAttributeElement in styleAttributeXmlNodeList)
			{
				//找到包含在xsl元素之外的第一个HTML元素，这个HTML元素被认为是需要条件格式的控件。
				XmlElement element = findParentHTMLElement(styleAttributeElement);
				if (element != null)
				{
					//对于按钮来说，按钮没有binding，但是如果没有binding的话，就不能以HTML ID作为标识进行动态更新，所以添加。
					//但是对于按钮来说，目前已经直接添加了HTML ID，在XSNViewFormatButtonWorker中。例子见Button Disable.xsn。
					
					//对于Section来说，它没有binding，见Section Shading.xsn，但是会在XSNViewFormatTemplateWorker已经设置Xslt Html Id属性({..})。

					string binding = element.GetAttribute(xdBinding);
					if (binding == null || binding.Length <= 0)
					{
						//element.setAttributeNS(JetConstant.URI_XD, xdBinding, ".");
                        //CID 0500 //2010.08.04 //Comment
						//element.SetAttribute(JetConstant.XD_binding, JetConstant.URI_XD, "."); //(1)
                        //CID 0500 //2010.08.04 //Comment
						//如果使用(1)设置xdBinding后,不能使用element.GetAttribute(xdBinding)得到.
						//所以必须使用(2)设置XmlAttribute节点。
						
						//这里没有发现必须设置"."的例子，但是仍然设置一下，防止有其它问题。
						//而且这个设置对按钮和Section没有影响。
						//使用(2)不会修改Section Id，会重新生成Button Id，所以这里需要过滤掉Button的情况。
						if( !isButtonControl( element ) )
						{
							XmlAttribute bindingAttr = view.Doc.CreateAttribute( view.XdPrefix, JetConstant.XD_binding, JetConstant.URI_XD );
							bindingAttr.Value = ".";
							element.SetAttributeNode( bindingAttr ); //(2)
						}
					}

                    //CID 0775 //2011.01.30 //Begin
                    XmlNodeList chooseWhenElementList = DOMUtil.selectNodes(styleAttributeElement, whenFilter, 0, view.NsResolver);
                    foreach (XmlElement chooseWhenElement in chooseWhenElementList)
                    {
                        string test = chooseWhenElement.GetAttribute("test");
                        string whenText = chooseWhenElement.InnerText;
                        int index = whenText.IndexOf("caption: InfoJetSoft.Attributes.");
                        if (index >= 0)
                        {
                            int nextIndex = whenText.IndexOf(";", index);
                            if (nextIndex < 0)
                            {
                                nextIndex = whenText.Length;
                            }
                            string caption = whenText.Substring(index, nextIndex - index);
                            string attr = caption.Replace("caption: InfoJetSoft.Attributes.", "");
                            string[] keyValue = attr.Split(new char[] { '=' });
                            if (keyValue.Length == 2)
                            {
                                string attrName = keyValue[0];
                                string attrValue = keyValue[1];
                                element.SetAttribute(attrName, attrValue);
                                chooseWhenElement.ParentNode.RemoveChild(chooseWhenElement);
                            }
                        }
                    }
                    //CID 0775 //2011.01.30 //End
				}
				//将这个条件格式的test记录到Manifest中。
				addConditionFormatTest( view, styleAttributeElement );
			}
		}

		private static bool isButtonControl( XmlElement element )
		{
			string name = element.Name.ToLower();
			if( name.Equals( "button" ) )
			{
				return true;
			}
			else if( name.Equals( "input" ) )
			{
				string type = element.GetAttribute( "type" );
				if( type != null && type.ToLower().Equals( "button" ) )
				{
					return true;
				}
			}
			return false;
		}

		//找到xsl:attribute/xsl:choose/xsl:when/@test，将test属性的值，添加到Manifest.ConditionFormatTestList。
		//Manifest.ConditionFormatTestList被用作判断是否ServerNode，见XSNManifestServerNodeWorker。
		private static void addConditionFormatTest( View view, XmlElement styleElement ){
			if( view.Manifest.ConditionFormatTestList == null )
			{
				view.Manifest.ConditionFormatTestList = new ArrayList();
			}
			string whenFilter = NamespaceUtil.toFullName(view.XslPrefix, "choose") + "/" + NamespaceUtil.toFullName(view.XslPrefix, "when");
			XmlElement whenElement = (XmlElement)DOMUtil.selectANode( styleElement, whenFilter, view.NsResolver );
			if( whenElement != null )
			{
				string test = whenElement.GetAttribute( "test" );
				if( test.Length > 0 )
				{
					view.Manifest.ConditionFormatTestList.Add( test );
				}
			}
		}

		
		//查找包含style元素的第一个非XSL元素。
		public static XmlElement findParentHTMLElement( XmlElement styleElement )
		{
			XmlElement parentElement = (XmlElement)styleElement.ParentNode;
			while( parentElement != null )
			{
				if( parentElement.NamespaceURI != null && parentElement.NamespaceURI.Equals( JetConstant.URI_XSL ) )
				{
				
				}
				else
				{
					return parentElement;
				}
				parentElement = (XmlElement)parentElement.ParentNode;
			}
			return null;
		}

	}
}